#include "qprojectcore.h"

#include "qprojecthost.h"
#include "qabstractproperty.h"
#include "qusermanager.h"
#include "qlanguagemanager.h"
#include "qpagemanager.h"
#include "xml.h"
#include "qprojectresource.h"
#include "qmemerymanager.h"
#include "qcommonstruct.h"
#include "qpageinfo.h"


#include <QXmlStreamWriter>
#include <QFile>
#include <QDir>
#include <QMessageBox>

using namespace SHAREDLIB;

QProjectCore*  QProjectCore::m_core=NULL;

QProjectCore::QProjectCore(QObject *parent) :
    QObject(parent),
    m_userManager(new QUserManager(this)),
    m_languageManager(new QLanguageManager(this)),
    m_pageManager(new QPageManager(this)),
    m_memeryManager(new QMemeryManager(this))
{
    connect(m_pageManager,SIGNAL(addPageSignal(SHAREDLIB::QPageInfo*)),this,SLOT(pageAdd(SHAREDLIB::QPageInfo*)));
    connect(m_pageManager,SIGNAL(delPageSignal(SHAREDLIB::QPageInfo*)),this,SLOT(pageDel(SHAREDLIB::QPageInfo*)));
    connect(m_languageManager,SIGNAL(languageAdd(QObject*,int)),this,SLOT(languageAdd(QObject*,int)));
    connect(m_languageManager,SIGNAL(languageNameChanged(QString,QString)),this,SLOT(languageNameChanged(QString,QString)));
    connect(m_userManager,SIGNAL(userAdd(QObject*,int)),this,SLOT(userAdd(QObject*,int)));
    connect(m_userManager,SIGNAL(userDel(QObject*)),this,SLOT(userDel(QObject*)));
    connect(m_languageManager,SIGNAL(languageDel(QObject*)),this,SLOT(languageDel(QObject*)));
    connect(m_userManager,SIGNAL(userNameChanged(QString,QString)),this,SLOT(userNameChanged(QString,QString)));
}

QProjectCore::~QProjectCore()
{
    delete m_host;
    delete m_userManager;
    delete m_languageManager;
    delete m_pageManager;
}

QProjectCore* QProjectCore::getCore()
{
    if(m_core==NULL)
    {
        m_core=new QProjectCore;
        m_core->m_host=new QProjectHost(m_core);
        m_core->m_host->setLanguageManager(m_core->m_languageManager);
    }
    return m_core;
}

void QProjectCore::releaseCore()
{
    if(m_core!=NULL)
    {
        delete m_core;
        m_core=NULL;
    }
}

QUserManager* QProjectCore::userManager()
{
    return m_userManager;
}

QLanguageManager* QProjectCore::languageManager()
{
    return m_languageManager;
}

QPageManager* QProjectCore::pageManager()
{
    return m_pageManager;
}

QMemeryManager *QProjectCore::memeryManager()
{
    return m_memeryManager;
}

void QProjectCore::open(const QString &filePath)
{
    closed();
    QFile f(filePath);

    if(f.open(QFile::ReadOnly))
    {
        QXmlStreamReader r(&f);

        while(!r.atEnd())
        {
            if(r.readNext()==QXmlStreamReader::StartElement)
            {
                if(r.name().toString()=="Object")
                {
                    QDir dir(filePath);
                    dir.cd("..");
                    m_projectPath=dir.path();
                    m_host->setNew();
                    m_host->setPropertyValue("path",m_projectPath);
                    loadProject(&r);
                    if(r.hasError())
                    {
                        qDebug(r.errorString().toLocal8Bit());
                        closed();
                        return;
                    }
                    userManager()->load(m_projectPath);
                    languageManager()->load(m_projectPath);
                    pageManager()->load(m_projectPath);
                    emit projectOpen();
                    QObject *obj=languageManager()->getCurrentLanguage();
                    if(obj==NULL)
                    {
                        obj=languageManager()->getLanguage(0);
                        languageManager()->setCurrentLanguage(obj);
                    }
                    QProjectResource::resource()->load(m_projectPath);
                    memeryManager()->load(m_projectPath);
                    m_host->setDefaultValue();
                }
            }
        }
    }
}

void QProjectCore::loadProject(QXmlStreamReader *r)
{
    XMLObject  xml;

    xml.read(r);
    if(r->hasError())
    {
        return;
    }

    QList<QAbstractProperty*>   pros=xml.propertys();
    SHAREDLIB::QAbstractProperty *temp;
    foreach(SHAREDLIB::QAbstractProperty* pro,pros)
    {
        temp=m_host->getProperty(pro->attribute("name").toString());
        if(temp!=NULL)
        {
            *temp=*pro;
            temp->setAttribute("NeedSave",true);
        }
    }
}

void QProjectCore::saveProject(QXmlStreamWriter *w)
{
    XMLObject xml;
    xml.setProperty("type","projectCore");
    QList<QAbstractProperty*>   pros=m_host->propertys();
    foreach(QAbstractProperty* pro,pros)
    {
        if(pro->attribute("NeedSave").toBool()
        || pro->attribute("modified").toBool())
        {
            xml.addProperty(pro);
        }
    }
    xml.write(w);
}

void QProjectCore::create(const QString &path, const QString &name)
{
    closed();
    m_projectPath=path;
    m_projectPath.replace("\\","/");

    QFile::remove(m_projectPath+"/language.xml");
    QFile::remove(m_projectPath+"/translate.xml");
    QFile::remove(m_projectPath+"/user.xml");
    QFile::remove(m_projectPath+"/pages.xml");
    QFile::remove(m_projectPath+"/config.pro");
    QFile::remove(m_projectPath+"/resource.rus");
    QFile::remove(m_projectPath+"/values.xml");

    m_host->setNew();
    userManager()->load(m_projectPath);
    languageManager()->load(m_projectPath);
    pageManager()->load(m_projectPath);
    QProjectResource::resource()->load(m_projectPath);
    memeryManager()->load(m_projectPath);

    addNewPage("form","main",":/files/temp.xml");
    m_host->setPropertyValue("objectName",name);
    m_host->setPropertyValue("path",path);
    m_host->setDefaultValue();
    save();
    emit projectOpen();
}

void QProjectCore::addNewForm(const QString &name, const QString &base_file)
{
    addNewPage("form",name,base_file);
}

void QProjectCore::addNewDialog(const QString &name, const QString &base_file)
{
    addNewPage("dialog",name,base_file);
}

void QProjectCore::addNewKeyboard(const QString &name, const QString &base_file)
{
    addNewPage("keyboard",name,base_file);
}

void QProjectCore::addNewPage(const QString &type, const QString &name, const QString &base_file)
{
    QPageInfo *info=new QPageInfo;
    info->set_type(type);
    info->set_name(name);
    QString str;
    if(base_file=="")
    {
        str=":/files/temp.xml";
    }
    else
    {
        str=base_file;
    }
    QFile f(str);
    if(f.open(QFile::ReadOnly))
    {
        str=f.readAll();
        f.close();
    }
    info->set_data(str);

    pageManager()->addPage(info);
}

void QProjectCore::closed()
{
    if(m_projectPath=="")
    {
        return;
    }
    emit projectClosed();
    m_host->clear();

    QStringList list1=pageManager()->property("oldForms").toStringList();
    QStringList list2=pageManager()->property("saveForms").toStringList();
    foreach(const QString str,list2)
    {
        list1.removeAll(str);
    }
    foreach(const QString str,list1)
    {
        QFile::remove(m_projectPath+"/pages/form/"+str+".xml");
    }
    pageManager()->clear();

    userManager()->release();

    languageManager()->release();

    QProjectResource::release();

    memeryManager()->clear();

    m_projectPath="";
}

QVariant QProjectCore::getPropertyValue(const QString &name)
{
    return m_host->getPropertyValue(name);
}

void QProjectCore::save()
{
    emit projectSave();
    QString path=m_projectPath;
    QDir d;
    d.mkpath(path);
    QFile f(path+"/config.pro");
    if(!f.open(QFile::WriteOnly))
    {
        return;
    }
    f.resize(0);
    QXmlStreamWriter    w(&f);
    w.setAutoFormatting(true);
    w.writeStartDocument();

    saveProject(&w);

    w.writeEndDocument();
    f.close();

    userManager()->save(m_projectPath);
    languageManager()->save(m_projectPath);
    pageManager()->save(m_projectPath);
    QProjectResource::resource()->save(m_projectPath);
    memeryManager()->save(m_projectPath);
}

QAbstractHost *QProjectCore::host()
{
    return m_host;
}

void QProjectCore::pageAdd(SHAREDLIB::QPageInfo *info)
{
    if(info->get_type()!="form")
    {
        return;
    }
    QAbstractProperty *pro=m_host->getProperty("start_page");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }
    tagComboItem item;
    item.m_text=info->get_name();
    item.m_value=info->get_name();
    items.append(item);
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);
    if(items.size()==1 && pro->getValue().toString()=="")
    {
        pro->setValue(item.m_value);
    }
}

void QProjectCore::languageAdd(QObject *obj,int index)
{
    QAbstractProperty *pro=m_host->getProperty("start_language");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }

    tagComboItem item;
    item.m_text=obj->property("languageName").toString();
    item.m_value=obj->property("languageName");
    items.insert(index,item);
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);
    if(items.size()==1 && pro->getValue().toString()=="")
    {
        pro->setValue(item.m_value);
    }
}

void QProjectCore::userAdd(QObject *obj,int index)
{
    QAbstractProperty *pro=m_host->getProperty("start_user");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }

    tagComboItem item;
    item.m_text=obj->property("userName").toString();
    item.m_value=obj->property("userName");
    items.insert(index,item);
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);
    if(items.size()==1 && pro->getValue().toString()=="")
    {
        pro->setValue(item.m_value);
    }
}

void QProjectCore::userDel(QObject *obj)
{
    QAbstractProperty *pro=m_host->getProperty("start_user");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }

    if(items.size()==0)
    {
        pro->setValue("");
        return;
    }

    for(int i=0;i<items.size();i++)
    {
        if(items.at(i).m_value==obj->property("userName"))
        {
            items.removeAt(i);
            break;
        }
    }
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);
    if(pro->getValue()==obj->property("userName"))
    {    if(items.size()==0)
        {
            pro->setValue("");
        }
        else
        {
            pro->setValue(items.first().m_value);
        }
    }
}

void QProjectCore::pageDel(SHAREDLIB::QPageInfo *info)
{
    if(info->get_type()!="form")
    {
        return;
    }
    QAbstractProperty *pro=m_host->getProperty("start_page");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }

    if(items.size()==0)
    {
        pro->setValue("");
        return;
    }

    for(int i=0;i<items.size();i++)
    {
        if(items.at(i).m_value==info->get_name())
        {
            items.removeAt(i);
            break;
        }
    }
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);
    if(pro->getValue()==info->get_name())
    {    if(items.size()==0)
        {
            pro->setValue("");
        }
        else
        {
            pro->setValue(items.first().m_value);
        }
    }
}

void QProjectCore::languageDel(QObject *obj)
{
    QAbstractProperty *pro=m_host->getProperty("start_language");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }

    if(items.size()==0)
    {
        pro->setValue("");
        return;
    }

    for(int i=0;i<items.size();i++)
    {
        if(items.at(i).m_value==obj->property("languageName"))
        {
            items.removeAt(i);
            break;
        }
    }
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);
    if(pro->getValue()==obj->property("languageName"))
    {    if(items.size()==0)
        {
            pro->setValue("");
        }
        else
        {
            pro->setValue(items.first().m_value);
        }
    }
}

void QProjectCore::languageNameChanged(const QString &old, const QString &now)
{
    QAbstractProperty *pro=m_host->getProperty("start_language");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }
    tagComboItem item;
    for(int i=0;i<items.size();i++)
    {
        item=items.at(i);
        if(item.m_value.toString()==old)
        {
            item.m_value=now;
            item.m_text=now;
            items.replace(i,item);
            break;
        }
    }
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);

    if(pro->getValue().toString()==old)
    {
        pro->setValue(now);
    }
}

void QProjectCore::userNameChanged(const QString &old, const QString &now)
{
    QAbstractProperty *pro=m_host->getProperty("start_user");
    ComboItems items;
    QVariant v=pro->attribute("items");
    if(v.isValid())
    {
        items=v.value<ComboItems>();
    }
    tagComboItem item;
    for(int i=0;i<items.size();i++)
    {
        item=items.at(i);
        if(item.m_value.toString()==old)
        {
            item.m_value=now;
            item.m_text=now;
            items.replace(i,item);
            break;
        }
    }
    v.setValue<ComboItems>(items);
    pro->setAttribute("items",v);

    if(pro->getValue().toString()==old)
    {
        pro->setValue(now);
    }
}
